import { Extension } from "@valuation/core";
import { Plugin, PluginKey } from "@rivet/state";
import type { Step } from "@rivet/transform";
export const historyKey: PluginKey = new PluginKey("changelogKey");
export interface ChangeState {
  steps: Step[];
}
export interface ChangeOptions {
  getChangeRecord?: (changes: any[], inverses: any[]) => void;
}
export const ChangelogExtension: Extension = Extension.create<
  ChangeOptions,
  ChangeState
>({
  name: "changelog",
  addStorage() {
    return {
      steps: [],
    };
  },
  addOptions() {
    return {
      getChangeRecord: () => void {},
    };
  },
  addRivetPlugins() {
    // deno-lint-ignore no-this-alias
    const that = this;
    return [
      new Plugin<Step[]>({
        key: historyKey,
        state: {
          init: (_config, _state) => {
            return [];
          },
          apply: (tr, _oldvalue, _state) => {
            that.storage.steps.push(...tr.steps);
            if (that.options.getChangeRecord) {
              let changes: any[] = [];
              let inverses: any[] = [];
              that.storage.steps.forEach((step: Step) => {
                changes = changes.concat(step.changes);
                inverses = inverses.concat(step.inverse);
              });
              that.options.getChangeRecord(changes, inverses);
            }
            return tr.steps;
          },
        },
      }),
    ];
  },
});
